﻿using System;
using System.IO;
using Microsoft.WowAddonStudio.FrameXml.Formats.Mpq;

namespace Microsoft.WowAddonStudio.Setup.CustomActions
{
    public class MpqExtractor
    {
        private const int bufferSize = 4096;

        private readonly ISession session;

        public MpqExtractor(ISession session)
        {
            if (session == null)
                throw new ArgumentNullException("session");

            this.session = session;
        }

        public void ExtractFromMpq(string mpqRelativePath, string filePath, string destinationFolder)
        {
            if (mpqRelativePath == null)
                throw new ArgumentNullException("mpqRelativePath");
            if (filePath == null)
                throw new ArgumentNullException("filePath");
            if (destinationFolder == null)
                throw new ArgumentNullException("destinationFolder");

            session.Log("Begin ExtractUiXsd");

            string wowPath = WowManager.GetWowPath();

            if (String.IsNullOrEmpty(wowPath)) 
            {
                session.Log("World of Warcraft installation not detected.");
                return;
            }

            string mpqPath = Path.Combine(wowPath, mpqRelativePath);
            string destinationFile = Path.Combine(destinationFolder, Path.GetFileName(filePath));

            session.Log("MpqPath: " + mpqPath);
            session.Log("FilePath: " + filePath);
            session.Log("DestinationFolder: " + destinationFolder);

            if (!File.Exists(mpqPath))
            {
                session.Log("Required MPQ file not found.");
                return;
            }

            if (!Directory.Exists(destinationFolder))
                Directory.CreateDirectory(destinationFolder);

            if (!MpqArchive.IsValidMpqArchive(mpqPath))
            {
                session.Log("Invalid MPQ archive.");
                return;
            }

            using (var mpqArchive = new MpqArchive(mpqPath))
            {
                if (!mpqArchive.FileExists(filePath))
                {
                    session.Log("File inside MPQ archive not found.");
                    return;
                }

                using (var mpqFile = mpqArchive.OpenFile(filePath))
                {
                    var buffer = new byte[bufferSize];

                    using (var destinationFileStream = File.Create(destinationFile))
                    using (var mpqStream = mpqFile.GetStream())
                    {
                        int bytesRead;
                        while ((bytesRead = mpqStream.Read(buffer, 0, bufferSize)) > 0)
                        {
                            destinationFileStream.Write(buffer, 0, bytesRead);
                        }
                    }
                }

                session.Log("File extracted from MPQ.");
            }
        }
    }
}